package org.teachertools.web.tag;

import java.util.Iterator;
import java.util.Locale;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.log4j.Logger;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.taglib.html.Constants;
import org.apache.struts.util.MessageResources;

/**
 * Custom tag that renders success messages if an appropriate request attribute has been created. The tag looks for a
 * request attribute with a reserved key, and assumes that it is either a String, a String array, containing message
 * keys to be looked up in the module's MessageResources, or an object of type
 * <code>org.apache.struts.action.ActionMessages</code>.
 * <p>
 * The following optional message keys will be utilized if corresponding messages exist for them in the application
 * resources:
 * <ul>
 * <li><b>success.header</b> - If present, the corresponding message will be rendered prior to the individual list of
 * error messages.</li>
 * <li><b>success.footer</b> - If present, the corresponding message will be rendered following the individual list of
 * error messages.</li>
 * <li><b>success.prefix</b> - If present, the corresponding message will be rendered before each individual error
 * message.</li>
 * <li><b>success.suffix</b> - If present, the corresponding message will be rendered after each individual error
 * message.</li>
 * </ul>
 * 
 * @author Dreamsoft
 * @version 1.0
 * @since 06/06/2005
 */
public class SuccessTag extends TagSupport {

    private static final Logger logger = Logger.getLogger(SuccessTag.class);

    // ----------------------------------------------------------- Properties
    private static final long serialVersionUID = -5378730025507233211L;

    public SuccessTag() {
        super();
    }

    /**
     * The servlet context attribute key for our resources.
     */
    protected String bundle = null;

    public String getBundle() {
        return (this.bundle);
    }

    public void setBundle(String pBundle) {
        this.bundle = pBundle;
    }

    /**
     * The default locale on our server.
     * 
     * @deprecated Use Locale.getDefault() directly.
     */
    @Deprecated
    protected static Locale defaultLocale = Locale.getDefault();

    /**
     * The line ending string.
     */
    protected static String lineEnd = System.getProperty("line.separator");

    /**
     * The session attribute key for our locale.
     */
    protected String locale = Globals.LOCALE_KEY;

    public String getLocale() {
        return (this.locale);
    }

    public void setLocale(String pLocale) {
        this.locale = pLocale;
    }

    /**
     * The message resources for this package.
     */
    protected static MessageResources messages = MessageResources.getMessageResources(Constants.Package
            + ".LocalStrings");

    /**
     * The request attribute key for our error messages (if any).
     */
    protected String name = Globals.MESSAGE_KEY;

    public String getName() {
        return (this.name);
    }

    public void setName(String pName) {
        this.name = pName;
    }

    /**
     * The name of the property for which error messages should be returned, or <code>null</code> to return all errors.
     */
    protected String property = null;

    public String getProperty() {
        return (this.property);
    }

    public void setProperty(String pProperty) {
        this.property = pProperty;
    }

    // ------------------------------------------------------- Public Methods

    /**
     * Render the specified error messages if there are any.
     * 
     * @exception JspException
     *                if a JSP exception has occurred
     */
    @Override
    public int doStartTag() throws JspException {
        boolean headerPresent = false;
        boolean footerPresent = false;
        boolean prefixPresent = false;
        boolean suffixPresent = false;
        try {
            headerPresent = TagUtils.getInstance()
                    .present(this.pageContext, this.bundle, this.locale, "success.header");

            footerPresent = TagUtils.getInstance()
                    .present(this.pageContext, this.bundle, this.locale, "success.footer");

            prefixPresent = TagUtils.getInstance()
                    .present(this.pageContext, this.bundle, this.locale, "success.prefix");

            suffixPresent = TagUtils.getInstance()
                    .present(this.pageContext, this.bundle, this.locale, "success.suffix");
        } catch (JspException e) {
            logger.warn("Can't get formating message resource", e);
        }

        // Were any error messages specified?
        ActionMessages actionMessages = null;
        TagUtils tagUtils = TagUtils.getInstance();
        try {
            actionMessages = tagUtils.getActionMessages(this.pageContext, this.name);
        } catch (JspException e) {
            // TagUtils.getInstance().saveException(this.pageContext, e);
            // throw e;
            logger.warn("Can't get struts action messages", e);
        }

        if ((actionMessages == null) || actionMessages.isEmpty()) {
            return (EVAL_BODY_INCLUDE);
        }

        // Render the error messages appropriately
        StringBuffer results = new StringBuffer();
        @SuppressWarnings("unchecked")
        Iterator<ActionMessage> reports = (this.property == null) ? actionMessages.get() : actionMessages
                .get(this.property);

        if (headerPresent) {
            String header = tagUtils.message(this.pageContext, this.bundle, this.locale, "success.header");
            results.append(header).append(lineEnd);
        }
        String prefix = tagUtils.message(this.pageContext, this.bundle, this.locale, "success.prefix");
        String suffix = tagUtils.message(this.pageContext, this.bundle, this.locale, "success.suffix");
        while (reports.hasNext()) {
            ActionMessage report = reports.next();

            if (prefixPresent) {
                results.append(prefix).append(lineEnd);
            }

            String message = tagUtils.message(this.pageContext, this.bundle, this.locale, report.getKey(), report
                    .getValues());
            if (message != null) {
                results.append(message).append(lineEnd);
            }

            if (suffixPresent) {
                results.append(suffix);
            }
        }

        if (footerPresent) {
            String footer = tagUtils.message(this.pageContext, this.bundle, this.locale, "success.footer");
            results.append(footer).append(lineEnd);
        }

        tagUtils.write(this.pageContext, results.toString());

        return (EVAL_BODY_INCLUDE);

    }

    /**
     * Release any acquired resources.
     */
    @Override
    public void release() {
        super.release();
        this.bundle = Globals.MESSAGES_KEY;
        this.locale = Globals.LOCALE_KEY;
        this.name = Globals.MESSAGE_KEY;
        this.property = null;
    }

}
